﻿using MyDelegate.Event;
using static MyDelegate.Student;

namespace MyDelegate
{
    internal class Program
    {
        /// <summary>
        /// DoRichardDelegate
        /// </summary>
        /// <param name="o"></param>
        public delegate void DoRichardDelegate(object? o);
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");


            try
            {
                //一、什么是委托，委托的本质是什么？ 
                //1.形似一个方法，修饰符，delegate关键字 是否有返回值，参数的列表
                //2.底层实现：ILSpy
                //3.所谓的委托：ILSpy反编译-识别底层---生成一个一个class, 如果定义在class外部：独立一个类出来，如果在内部，生成了一个类中类；继承自：[System.Runtime]System.MulticastDelegate  特殊类
                //4. 构造函数
                //5. 实例方法
                // 委托的本质：就是一个类---就当类来使用；


                {
                    CustomDelegate.Show();
                }

                //二、委托的实例化，执行委托 
                //1.实例化一个委托：必须要传入一个和当前委托的参数 和返回值完全吻合的方法；
                //2.如果执行委托--执行Invoke方法，就会把指向这个委托的方法给执行掉； 还是执行方法

                // 形态上理解下委托：
                // 委托--class    可以指向（包含一段业务逻辑），类的实例----可以当做参数来传递；参数传递之后，如果执行委托，其实执行的是方法；
                //委托：可以把一个方法当做参数来传递；
                //委托：可以传递行为的，是一个包装方法的盒子；


                //三、委托的作用和意义（可以怎么用？哪些场景？？）
                {
                    Student student = new Student() { Id = 123, Name = "夕林吹雪" };
                    student.SayHi(UserType.Wuhan);

                    // 问好的方式有多种；
                    //WuHan 人： 吃了么？
                    //GuanDong 人：靓仔/靓女~ 雷猴！
                    //BeiJing 人： 你好！

                    //问题一：如果想要增加一个地方的人；

                    Console.WriteLine("为每一个地方的人分别定义逻辑 \r\n");
                    //解决方案一：（多增加几个方法）可以为每一个地方的人，各自定义一个方法
                    student.SayHiWuHan();
                    student.SayHiGuanDong();
                    student.SayHiBeiJing();

                    Console.WriteLine("传递枚举分辨逻辑执行 \r\n");
                    //解决方案二：（传递参数来判断）
                    student.SayHi(UserType.Wuhan);
                    student.SayHi(UserType.BeiJing);
                    student.SayHi(UserType.GuangDong);

                    //思考下：方案一和方案二，二者哪个更优秀？  
                    //现在是20:54，中场休息6分钟，21:00 继续，现在Richard老师不说话了~~

                    //点评：
                    //方案一：更好---每个方案，可以相互独立，互不干扰，逻辑没有解耦；满足单一职责；
                    //方案二：耦合在一起，如果有需求的升级，可能需要修改原有的方案，代码可能会不稳定；

                    //问题二：如果我想要增加一些公共的业务逻辑呢？问好前---伴随一个动作---“招招手”
                    //再比较：方案二更有有优势了；  只需要增加一句，就可以覆盖所有的人；
                    //        方案一出现了重复代码；


                    //有没有一个完美方案呢？ 
                    Console.WriteLine("通过委托传递逻辑 \r\n");
                    DoHandlerDelegate doHandlerWuhan = new DoHandlerDelegate(student.SayHiWuHan);
                    student.SayHiPerfect(doHandlerWuhan);

                    DoHandlerDelegate doHandlerBeiJin = new DoHandlerDelegate(student.SayHiBeiJing);
                    student.SayHiPerfect(doHandlerBeiJin);

                    DoHandlerDelegate doHandlerGuangDong = new DoHandlerDelegate(student.SayHiGuanDong);
                    student.SayHiPerfect(doHandlerGuangDong);

                    //问题一：增加一个上海人 --- 增加了一个方案； 方法单一； 方法相互独立，互不干扰；--稳定性，逻辑解耦
                    //问题二：增加一个公共的业务逻辑，只需要在SayHiPerfect 增加一个动作即可；去掉重复代码；

                    DoHandlerDelegate doHandlerShangHi = new DoHandlerDelegate(student.SayShangHai);
                    student.SayHiPerfect(doHandlerShangHi);
                    //委托的价值：
                    //1.逻辑解耦,代码的职责单一
                    //2.去掉重复代码

                    //建议： 如果代码中出现了严重的耦合----考虑使用委托来解决下
                    //       如果代码中，出现了大量的重复代码----考虑使用委托来解决下

                }

                //委托的价值，应用
                //四、框架内置委托Action/Func
                {
                    ActionFunc.Show();
                }


                //五、委托的嵌套使用,ASP.NET Core中间件的核心设计--委托的多层嵌套 
                {
                    //委托里面可以嵌套一个委托  委托的盒子中，装一个委托；
                    DelegateExtension.Show();

                }

                Console.WriteLine("=====================================================================多播委托");
                //六、多播委托/观察者模式
                {
                    new CustomMulticastDelegation().Show();
                }

                //七、多播委托的应用--观察者模式
                {
                    Console.WriteLine("=========================================");
                    Console.WriteLine("=========================================通过oop的思想 继承");
                    {
                        Cat cat = new Cat();
                        cat.ObserList.Add(new Baby());
                        cat.ObserList.Add(new Mother());
                        cat.ObserList.Add(new Dog());
                        cat.ObserList.Add(new Mouse());
                        cat.ObserList.Add(new Father());
                        cat.ObserList.Add(new Neighbor());
                        cat.ObserList.Add(new Stealer());
                        cat.MiaoObserver();
                    }


                    Console.WriteLine("=========================================");
                    Console.WriteLine("=========================================通过委托实现");
                    {
                        Cat cat = new Cat();
                        cat.ActionHander += new Baby().Cry;
                        cat.ActionHander += new Mother().Wispher;
                        cat.ActionHander += new Dog().Wang;
                        cat.ActionHander += new Mouse().Run;
                        cat.ActionHander += new Father().Roar;
                        cat.ActionHander += new Neighbor().Awake;
                        cat.ActionHander += new Stealer().Hide;

                        //cat.ActionHander -= new Baby().Cry;
                        //  cat.ActionHander.Invoke();// 委托可以在定义委托所在类的外部去执行；
                        cat.Miao();
                    }

                    Console.WriteLine("=========================================");
                    Console.WriteLine("事件的应用：============================");
                    {
                        Cat cat = new Cat();
                        cat.ActionHanderEvent += new Baby().Cry;
                        cat.ActionHanderEvent += new Mother().Wispher;
                        cat.ActionHanderEvent += new Dog().Wang;
                        cat.ActionHanderEvent += new Mouse().Run;
                        cat.ActionHanderEvent += new Father().Roar;
                        cat.ActionHanderEvent += new Neighbor().Awake;
                        cat.ActionHanderEvent += new Stealer().Hide;
                        // cat.ActionHanderEvent -= new Baby().Cry;
                        //cat.ActionHanderEvent.Invoke();
                        cat.MiaoEvent();
                    }

                    //事件：发布订阅（和观察者很像） 
                    {
                        //Console.WriteLine("自定义标准事件--实现发布订阅====================================================");
                        //EventStandard.Init();  //订阅者和发布者二者之间的联系
                        //EventStandard.Show();
                    }
                }





                //事件：发布订阅（和观察者很像） 
                {
                    Console.WriteLine("自定义标准事件--实现发布订阅====================================================");
                    EventStandard.Init();  //订阅者和发布者二者之间的联系
                    EventStandard.Show();
                }





            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }




            Console.ReadKey();
        }
    }
}
